home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / c / driver.com / DRIVER.ASM < prev    next >
Encoding:
Assembly Source File  |  1991-07-09  |  4.2 KB  |  137 lines

  1. ;
  2. ; This file provides the lowlevel interface needed for creating a DOS
  3. ; device driver. This module is designed to be assembled using Borlands
  4. ; TASM. All you need to do is modify the C module _handler to suit your
  5. ; needs and then link everything together.
  6. ;
  7. ; As usual you may use these modules as you please without paying me anything
  8. ; unless of course you want to pay me, I could always use another trip to the
  9. ; Bahamas.  If you would like to ask me anything just send E-Mail to
  10. ; 76207,674 
  11.  
  12. DONE        equ    0100h    ; operation complete bit
  13.  
  14.         .model    small    ; memory models must match between all modules
  15.         .286        ; you could change this to what ever you wish
  16.         .code        ; simplified segment directives make segments
  17.                 ; match C segment directives
  18. extrn        _handler:near    ; external C module
  19.  
  20.         org    0    ; all device drivers start at location 0
  21. ;
  22. ; the following header is required in all device drivers
  23. header        dd    -1    ; pointer to next driver in the chain
  24. attribute    dw    8000h    ; character device 
  25.         dw    offset strategy        ; offset to stratgey routine
  26.         dw    offset interrupt    ; offset to interrupt routine
  27.         db    'GENERIC$'        ; driver name 8 bytes padded
  28. ;
  29. ; end of header
  30. ;
  31.  
  32. ;
  33. ; local data
  34. ;        
  35. request_header    dd    ?    ; address of DOS request header
  36. oldss        dw    ?    ; old stack segment
  37. oldsp        dw    ?    ; old stack pointer
  38.  
  39. local_stack    db    128 dup ('stack   ')    ; 1k local stack
  40. tos        dw    ?            ; top of stack
  41.  
  42. ;
  43. ; The strategy routine just stores the address of the request header.
  44. ; When DOS calls the device driver it first calls the strategy routine
  45. ;
  46. strategy    proc    far
  47.         mov    word ptr cs:[request_header],bx
  48.         mov    word ptr cs:[request_header+2],es
  49.         ret
  50. strategy    endp
  51.  
  52. ;
  53. ; DOS calls the interrupt routine after the stratgey routine returns
  54. ;        
  55. interrupt    proc    far    
  56.         pushf        ; we need to save the state of the machine
  57.         push    ax    ; since we're being called from the kernel
  58.         push    bx
  59.         push    cx
  60.         push    dx
  61.         push    ds
  62.         push    es
  63.         push    si
  64.         push    di
  65.         push    bp
  66.  
  67. ;
  68. ; we establish our own data segment and make it equal to the code segment
  69. ; since our local data is located in code segment
  70. ;
  71.         push    cs
  72.         pop    ds        
  73. ;
  74. ; Load es:bx with the address of the request header, DOS passes information
  75. ; to the device driver through the request header
  76. ;        
  77.         les    bx,[request_header]
  78.  
  79. ;
  80. ; Now we save the current stack and setup our own stack incase the calling
  81. ; program doesn't have enough stack space available for the driver
  82. ;
  83.         mov    word ptr oldss,ss    ; save stack segment
  84.         mov    word ptr oldsp,sp    ; save stack pointer
  85.         mov    ax,cs            ; get our stack segment
  86.         mov    ss,ax            ; establish stack
  87.         mov    sp,offset tos - 2    ; and pointer
  88.  
  89. ; Now push the request header address on the stack and and call the
  90. ; C routine using the TASM language independent calling feature
  91. ; Just call the routine specifing the language followed by the parms
  92. ; TASM will push the parms on the stack in the correct order and adjust
  93. ; the stack when the routine returns
  94. ;
  95.         call    _handler C,BX,ES    
  96. ;        
  97. ; Note: on 80x86 machines segment:offset memory variables are referenced in
  98. ; reverse order so the variable addressed by es:bx is stored in memory with
  99. ; bx in the first word and es in the second word. In the above call bx is 
  100. ; before es because we pass variables to C functions on the stack which is
  101. ; just physical memory referenced by SS and SP
  102. ;
  103. ; AX contains status code returned from _handler which is declare as 
  104. ; int handler(RequestHeader far *) in the C file
  105. ;
  106. ; Now that we are back we must restore the original stack and finish
  107. ; processing the driver code
  108. ;
  109.         push    cs    ; let's restore our data segment since it got
  110.         pop    ds    ; changed in the C module
  111.  
  112.         mov    ss,word ptr oldss    ; restore original stack seg
  113.         mov    sp,word ptr oldsp    ; and stack pointer
  114.  
  115. ;
  116. ; The remaining code restores the machine state and then returns telling
  117. ; DOS that the operation is complete
  118. ;
  119. finish:        les    bx,[request_header] ; get address of request header
  120.         or    ax,DONE        ; set completion bit
  121.         mov    es:[bx]+3,ax    ; store it in the request header
  122.         pop    bp        ; restore all registers
  123.         pop    di
  124.         pop    si
  125.         pop    es
  126.         pop    ds
  127.         pop    dx
  128.         pop    cx
  129.         pop    bx
  130.         pop    ax
  131.         popf
  132.         ret    ; and return to DOS, this is not a real interrupt
  133.             ; routine so we don't need an IRET
  134. interrupt    endp
  135.  
  136.         end